#include "thread_mgr.h"
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <iostream>

thread_mgr::thread_mgr()
{

}
///*********************************************************************************************************///
///
///
///
///
/// \brief thread_func_1, without param
///
void thread_func_1()
{
    std::cout << "this is thread_func_1" << std::endl;
}

///
/// \brief thread_func_2
/// \param param
///
void thread_func_2(std::string param)
{
    std::cout << "this is thread_func_2" << std::endl
                 << "the param = " << param << std::endl;
}

///
/// \brief The callable_1 struct
///
struct callable_1
{
    void operator ()()
    {
        std::cout << "this is callable_1" << std::endl;
    }
};

///
/// \brief The callable_2 struct
///
struct callable_2
{
    void operator ()(std::string param)
    {
        std::cout << "this is callable_2" << std::endl
                     << "the param = " << param << std::endl;
    }
};

///
/// \brief main_exit
///
void main_exit()
{
    std::cout << "main exit" << std::endl;
}

///
/// \brief thread_mgr::test_create_thread
///
void thread_mgr::test_create_thread()
{
    boost::this_thread::at_thread_exit(&main_exit);

    boost::thread(&thread_func_1).join();
    boost::thread(&thread_func_2, "hello").join();
    boost::thread(callable_1()).join();
    boost::thread(callable_2(), "world").join();
}


///*************************************************************************************************///

///
/// \brief thread_func_3, sleep_for()
///
void thread_func_3()
{
    for(int i=0; i<5; i++)
    {
        boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));
        std::cout << "i = " << i << std::endl;
    }
}

///
/// \brief thread_func_4, sleep_until()
///
void thread_func_4()
{
    std::cout << "before sleep: " << boost::chrono::system_clock::now() << std::endl;
    boost::this_thread::sleep_until(boost::chrono::system_clock::now() + boost::chrono::milliseconds(3000));
    std::cout << "after sleep: " << boost::chrono::system_clock::now() << std::endl;
}

///
/// \brief thread_mgr::test_thread_sleep
///
void thread_mgr::test_thread_sleep()
{
    boost::thread(&thread_func_3).join();
    boost::thread(&thread_func_4).join();
}

///**********************************************************************************************************///

void thread_func_5()
{
    boost::this_thread::sleep_for(boost::chrono::milliseconds(3000));
    std::cout << "sleep finished" << std::endl;
}

void thread_mgr::test_thread_join_scoped()
{
//    /// without join
//    {
//        boost::thread thread((&thread_func_5));
//        std::cout << "main thread finished" << std::endl;
//    }
//    /// without join
//    {
//        boost::thread(&thread_func_5).join();
//        std::cout << "main thread finished" << std::endl;
//    }
//    ///scoped thread
//    {
//        boost::scoped_thread<> thread((&thread_func_5));
//        std::cout << "main thread finished" << std::endl;
//    }
//    ///strict scoped thread
//    {
//        boost::strict_scoped_thread<> thread((&thread_func_5));
//        std::cout << "main thread finished" << std::endl;
//    }
//    ///scoped thread functor detach
//    {
//        boost::strict_scoped_thread<boost::detach> thread((&thread_func_5));
//        std::cout << "main thread finished" << std::endl;
//    }
//    ///scoped thread functor join_if_joinable
//    {
//        boost::strict_scoped_thread<boost::join_if_joinable> thread((&thread_func_5));
//        std::cout << "main thread finished" << std::endl;
//    }
//    /// scoped thread functor interrupt_and_join_if_joinable
//    {
//        boost::strict_scoped_thread<boost::interrupt_and_join_if_joinable> thread((&thread_func_5));
//        std::cout << "main thread finished" << std::endl;
//    }
}

///*************************************************************************************************************///

///
/// \brief thread_func_6
///
void thread_func_6()
{
    boost::this_thread::sleep_for(boost::chrono::seconds(3));
    std::cout << "thread_func_6 finished" << std::endl;
}

///
/// \brief thread_func_7
///
void thread_func_7()
{
    for(int i=0; i<100000; i++)
    {
        std::cout << "i = " << i << std::endl;
    }
    std::cout << "thread_func_7 finished" << std::endl;
}

///
/// \brief thread_func_8
///
void thread_func_8()
{
    {
        boost::this_thread::disable_interruption di;
        boost::this_thread::sleep_for(boost::chrono::seconds(3));
        std::cout << "thread_func_8 finished" << std::endl;
    }
}

boost::thread *g_thread;
///
/// \brief thread_func_10
///
void thread_func_10()
{
     g_thread = new boost::thread(&thread_func_7);
     g_thread->join();
}


///
/// \brief thread_mgr::test_thread_interrupt
///
void thread_mgr::test_thread_interrupt()
{
//    ///interrupt thread_func_6
//    {
//        boost::thread thread(&thread_func_6);
//        boost::this_thread::sleep_for(boost::chrono::seconds(1));
//        thread.interrupt();
//        thread.join();
//        std::cout << "main thread finished" << std::endl;
//    }
//    /// interrupt thread_func_7
//    {
//        boost::thread thread(&thread_func_7);
//        boost::this_thread::sleep_for(boost::chrono::seconds(1));
//        thread.interrupt();
//        std::cout << "main thread finished" << std::endl;
//    }
//    /// interrupt thread_func_8
//    {
//        boost::thread thread(&thread_func_8);
//        boost::this_thread::sleep_for(boost::chrono::seconds(1));
//        thread.interrupt();
//        thread.join();
//        std::cout << "main thread finished" << std::endl;
//    }

//    boost::thread thread(&thread_func_10);
//    boost::this_thread::sleep_for(boost::chrono::seconds(1));
//    g_thread->interrupt();
//    boost::this_thread::sleep_for(boost::chrono::seconds(2));
//    std::cout << "main thread finished" << std::endl;

}

///*********************************************************************************************///

///
/// \brief thread_func_9
///
void thread_func_9()
{
    boost::this_thread::sleep_for(boost::chrono::seconds(1));
    std::cout << "thread_func_9 finished" << std::endl;
}

///
/// \brief thread_mgr::test_thread_others
///
void thread_mgr::test_thread_others()
{
    boost::thread thread(&thread_func_9);
    std::cout << "thread id = " << thread.get_id() << std::endl;
    std::cout << "hardware concurrency = " << thread.hardware_concurrency() << std::endl;
    std::cout << "physical concurrency = " << thread.physical_concurrency() << std::endl;
    std::cout << "native handle = " << thread.native_handle() << std::endl;
    thread.join();
}
